package top.malaoshi.data;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class OrderBy {

    public enum Sort {
        /**
         * 升序
         */
        asc,
        /**
         * 降序
         */
        desc
    }
    protected DataTable dataTable;

    public OrderBy(DataTable dataTable){
        this.dataTable = dataTable;
    }

    /**
     * 封装列、排序
     */
    private static class ColumnAndSort{
        private String column;
        private Sort sort;
        public ColumnAndSort(String column,Sort sort){
            this.column = column;
            this.sort = sort;
        }
        public static ColumnAndSort of(String column,Sort sort){
            return new ColumnAndSort(column,sort);
        }
    }
    List<ColumnAndSort> columns = new ArrayList<>();
    public OrderBy orderBy(String column, Sort sort) {
        columns.add(ColumnAndSort.of(column,sort));
        return this;
    }

    public DataTable getResult(){
        DataTable retTable = dataTable.copy();
        List<DataRow> dataRows = retTable.rows().getDataRows();
        dataRows.sort(new ComparatorImpl(0));
        return retTable;
    }

    public class ComparatorImpl implements Comparator<DataRow> {
        private int index = 0;
        ComparatorImpl(int index){
            this.index = index;
        }
        @Override
        public int compare(DataRow r1, DataRow r2) {
            int i = index;
            ColumnAndSort columnAndSort = columns.get(i);
            String column = columnAndSort.column;
            DataColumn dataColumn = dataTable.columns().get(column);
            if(dataColumn.getType() == DataColumn.Type.INT ){
                Integer o1 =  r1.getIntValue(column);
                Integer o2 =  r2.getIntValue(column);

                if(o1==null && o2!=null){
                    if(columnAndSort.sort == Sort.asc) {
                        return -1;
                    }else{
                        return 1;
                    }
                }else if(o1!=null && o2==null){
                    if(columnAndSort.sort == Sort.asc) {
                        return 1;
                    }else{
                        return -1;
                    }
                }else if(o1==null && o2==null){
                    if(columns.size() == index + 1){
                        return 0;
                    }
                    return new OrderBy.ComparatorImpl(index+1).compare(r1,r2);
//                        return 0;
                }else {
                    int res = o1 - o2;
                    if(res == 0){
                        if(columns.size() == index + 1){
                            return 0;
                        }
                        return new OrderBy.ComparatorImpl(index+1).compare(r1,r2);
                    }else{
                        if(columnAndSort.sort == Sort.asc) {
                            return res;
                        }else{
                            return -res;
                        }
                    }
                }

            }else if(dataColumn.getType() == DataColumn.Type.DOUBLE){
                Double o1 = r1.getDoubleValue(column);
                Double o2 = r2.getDoubleValue(column);

                if(o1==null && o2!=null){
                    if(columnAndSort.sort == Sort.asc) {
                        return -1;
                    }else{
                        return 1;
                    }
                }else if(o1!=null && o2==null){
                    if(columnAndSort.sort == Sort.asc) {
                        return 1;
                    }else{
                        return -1;
                    }
                }else if(o1==null && o2==null){
                    if(columns.size() == index + 1){
                        return 0;
                    }
                    return new OrderBy.ComparatorImpl(index+1).compare(r1,r2);
//                        return 0;
                }else {
                    if(o1 < o2) {
                        if(columnAndSort.sort == Sort.asc) {
                            return -1;
                        }else{
                            return 1;
                        }
                    }else if(o1 == o2){
                        if(columns.size() == index + 1){
                            return 0;
                        }
                        return new OrderBy.ComparatorImpl(index+1).compare(r1,r2);
//                            return 0;
                    }else{
                        if(columnAndSort.sort == Sort.asc) {
                            return 1;
                        }else{
                            return -1;
                        }
                    }
                }

            }else if(dataColumn.getType() == DataColumn.Type.TEXT){
                String o1 = r1.getStringValue(column);
                String o2 = r2.getStringValue(column);

                if(o1==null && o2!=null){
                    if(columnAndSort.sort == Sort.asc) {
                        return -1;
                    }else{
                        return 1;
                    }
                }else if(o1!=null && o2==null){
                    if(columnAndSort.sort == Sort.asc) {
                        return 1;
                    }else{
                        return -1;
                    }
                }else if(o1==null && o2==null){
//                        return 0;
                    if(columns.size() == index + 1){
                        return 0;
                    }
                    return new OrderBy.ComparatorImpl(index+1).compare(r1,r2);
                }else {
                    int res = o1.compareTo(o2);

                    if(res == 0){
                        if(columns.size() == index + 1){
                            return 0;
                        }
                        return new OrderBy.ComparatorImpl(index+1).compare(r1,r2);
                    }else{
                        if(columnAndSort.sort == Sort.asc) {
                            return res;
                        }else{
                            return -res;
                        }
                    }
                }

            }else{
                throw new DataColumnTypeNotSupportedException(column,dataColumn.getType(),"不支持此操作！");
            }

        }
    }
}
